﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using ATEC.GeometryNET;
using SSDPNET.Geom;
using ATEC.ATDataCoreNET;
using DynamicButtons;
using System.Diagnostics;

namespace GeometryExample
{
    /// <summary>
    /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建。
    /// 内容：玄镜BIM图形平台上，几何对象，如点、线、面的创建的例子.
    /// </summary>
    public class CreateCurveSetMethods
    {
        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建。
        /// 功能：弹出四个按钮，分别演示创建线段(XSegment)、创建线串(多点折线，类型为基本曲线BasicCruve)、创建圆弧、创建B样条曲线.
        /// </summary>
        public static void CreateGeometryExample()
        {
            //清空视口
            UseSomeBasicMethods.ClearScene();

            ButtonsView v = new ButtonsView();

            v.AddButton("创建线段", (object sender, RoutedEventArgs e) =>
            {
                CreateXSegment3dExample();
            });

            v.AddButton("创建线串", (object sender, RoutedEventArgs e) =>
            {
                CreateLineStringExample();
            });

            v.AddButton("创建圆弧", (object sender, RoutedEventArgs e) =>
            {
                CreateXEllipse3dExample();
            });

            v.AddButton("创建B样条曲线", (object sender, RoutedEventArgs e) =>
            {
                CreateBsplineCurvesExample();
            });


            v.Show();

        }


        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/创建线段。
        /// 功能：构造一个线段，并加入到玄镜图形平台场景.
        /// 关键类及说明：
        ///     XSegment3d: 线段，三维. 
        /// </summary>
        public static void CreateXSegment3dExample()
        {
            //构造线段
            XSegment3d seg = CreateXSegmentFromStartEnd();
            //添加到场景
            UseSomeBasicMethods.AddToScene_XSegment(seg, 1);
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/创建线串。
        /// 功能：构造一个线串，并加入到玄镜图形平台场景.
        /// 关键类及说明：
        ///     BasicCurve: 基本曲线，抽象类。可以表示多段线、弧（圆弧、椭圆）、螺旋线、B样条曲线等基本线型。
        /// </summary>
        private static void CreateLineStringExample()
        {
            //创建多段线
            BasicCurve basic = CreateLineStringFromPts();
            //添加到场景
            UseSomeBasicMethods.AddToScene_BasicCurve(basic, 2);
        }


        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/创建弧。
        /// 功能：构造一个圆弧，并加入到玄镜图形平台场景. 演示两种创建方法：1 根据圆心、半径、法向量创建圆弧 2 根据圆心、起点、终点创建圆弧
        /// 关键类及说明：
        ///     XEllipse3d: 椭圆，或椭圆的一段弧；也可以表示圆，或圆的一段弧
        /// </summary>
        public static void CreateXEllipse3dExample()
        {
            //构造圆/圆弧
            ButtonsView v = new ButtonsView();
            v.AddButton("根据圆心，半径，法向量创建圆", (object sender, RoutedEventArgs e) =>
            {
                XEllipse3d arc1 = CreateXEllipse3d_FromCenterRadiusNormal();

                //添加到视口
                UseSomeBasicMethods.AddToScene_XEllipse3d(arc1, 3);
            });

            v.AddButton("根据圆心，起点，终点创建圆弧", (object sender, RoutedEventArgs e) =>
            {
                XEllipse3d arc2 = CreateXEllipse3d_FromCenterStartEndPts();

                //添加到视口
                UseSomeBasicMethods.AddToScene_XEllipse3d(arc2, 4);
            });
            v.Show();

            //创建圆弧的其他方法，根据需要添加到视口查看
            XEllipse3d arc3 = CreateXEllipse3d_FromFraction();
            XEllipse3d arc4 = CreateXEllipse3d_Reverse();
            SSDPNET.ValidatedXEllipse3d arc5 = CreateXEllipse3d_FromStartPtTangentNormalRadiusSweep();
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/创建B样条曲线。
        /// 功能：构造一个圆弧，并加入到玄镜图形平台场景. 演示两种创建方法：1 根据控制点创建B样条曲线 2 根据通过点创建B样条曲线
        /// 关键类及说明：
        ///     ATBsplineCurve: B样条曲线.
        /// </summary>
        public static void CreateBsplineCurvesExample()
        {
            //构造ATBSplineLine
            ButtonsView v = new ButtonsView();

            v.AddButton("提供控制点创建B样条曲线", (object sender, RoutedEventArgs e) =>
            {
                ATBsplineCurve bspine2 = CreateATBsplineCurves_FromControlPts(true);
                //添加到视口
                UseSomeBasicMethods.AddToScene_ATBsplineCurve(bspine2, 5);
            });

            v.AddButton("提供通过点创建B样条曲线", (object sender, RoutedEventArgs e) =>
            {
                ATBsplineCurve bspine4 = CreateATBsplineCurves_FromThroughPts(true);
                //添加到视口
                UseSomeBasicMethods.AddToScene_ATBsplineCurve(bspine4, 6);
            });
            v.Show();


        }


        #region 构造圆
        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建圆.
        /// 功能：构造一个圆. 方式为，根据圆心、半径、法向量.
        /// 关键类及说明：
        ///     XPoint3d: 三维点，表示圆心。
        ///     XVector3d: 三维向量，表示圆所在平面的法向量。
        /// </summary>
        public static XEllipse3d CreateXEllipse3d_FromCenterRadiusNormal()
        {
            //根据圆心，半径，法向量创建圆
            XPoint3d center = XPoint3d.Zero;
            double radius = 50;
            XVector3d normal = XVector3d.UnitZ;
            XEllipse3d arc1 = XEllipse3d.FromCenterRadiusNormal(center, radius, normal);
            return arc1;

        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建圆.
        /// 功能：构造一个圆. 方式为，根据圆心、起点、终点
        /// 关键类及说明：
        ///     XPoint3d: 三维点，表示圆心。
        ///     XVector3d: 三维向量，表示圆所在平面的法向量。
        ///     XEllipse3dExtension: XEllipse3d 的扩展类，提供额外的构造XEllipse的方法。
        /// </summary>
        public static XEllipse3d CreateXEllipse3d_FromCenterStartEndPts()
        {
            //根据圆心，起点，终点创建圆弧
            XPoint3d center = new XPoint3d(55, 0, 0);
            XPoint3d stPt = center - XVector3d.UnitX * 50;
            XPoint3d edPt = center + XVector3d.UnitY * 50;
            XEllipse3d arc2 = XEllipse3dExtension.FromArcCenterStartEnd(center, stPt, edPt);
            return arc2;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建圆弧.
        /// 功能：构造一个圆弧. 方式为，根据圆心、起点、终点
        /// 关键类及说明：
        ///     XPoint3d: 三维点，表示圆心。
        ///     XVector3d: 三维向量，表示圆所在平面的法向量。
        ///     XEllipse3dExtension: XEllipse3d 的扩展类，提供额外的构造XEllipse的方法。
        /// 关键方法：
        ///     XEllipse3dExtension.FromFractionInterval: 根据分数区间，截取一段圆弧.
        /// </summary>
        public static XEllipse3d CreateXEllipse3d_FromFraction()
        {
            //获取已知圆的起始比例-终止比例之间的圆弧
            XEllipse3d arc2 = CreateXEllipse3d_FromCenterStartEndPts();
            double startFraction = 0.2;
            double endFraction = 0.8;
            //截取整圆中分数比例在0.2-0.8之间的圆弧
            XEllipse3d arc3 = XEllipse3dExtension.FromFractionInterval(arc2, startFraction, endFraction);
            return arc3;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建圆弧.
        /// 功能：构造一个圆弧. 并反向.
        /// 关键类及说明：
        ///     XEllipse3dExtension: XEllipse3d 的扩展类，提供额外的构造XEllipse的方法。
        /// 关键方法：
        ///     XEllipse3dExtension.FromReversed: 构造输入圆弧的反向弧
        /// </summary>
        public static XEllipse3d CreateXEllipse3d_Reverse()
        {
            //反转已知圆弧【改变圆弧的顺逆时针】
            XEllipse3d arc3 = CreateXEllipse3d_FromFraction();
            XEllipse3d arc4 = XEllipse3dExtension.FromReversed(arc3);
            return arc4;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建圆弧.
        /// 功能：构造一个圆弧. 根据起点及切向、目标圆所在面的法向、目标圆半径、弧度角.
        /// 关键类及说明：
        ///     XEllipse3dExtension: XEllipse3d 的扩展类，提供额外的构造XEllipse的方法。
        /// 关键方法：
        ///     XEllipse3dExtension.FromStartTangentNormalRadiusSweep: 根据起点及切向、目标圆所在面的法向、目标圆半径、弧度角.
        /// </summary>
        public static SSDPNET.ValidatedXEllipse3d CreateXEllipse3d_FromStartPtTangentNormalRadiusSweep()
        {
            //由起始点，起始切线，面法向量，半径和扫掠角度创建椭圆弧
            XPoint3d ptA = new XPoint3d(0, 0, 0);
            XVector3d tangent = XVector3d.UnitX;
            XVector3d normal = XVector3d.UnitZ;
            double radius = 50;
            double sweepRadians = Math.PI/2;//扫掠角度设置为PI/2

            //ValidatedXEllipse3d 该类可以判断圆弧的有效性
            SSDPNET.ValidatedXEllipse3d validEllipse = SSDPNET.Geom.XEllipse3dExtension.FromStartTangentNormalRadiusSweep(ptA, tangent, normal, radius, sweepRadians);
            bool isValid = validEllipse.IsValid();
            return validEllipse;
        }
        #endregion

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建多段线.
        /// 功能：构造一个多段线.
        /// 关键类及说明：
        ///     BasicCurve: 基本曲线。此例中表示多段线， basic.GetBasicCurveType() == BasicCurve.BasicCurveType.LineString
        /// 关键方法：
        ///     BasicCurve.CreateLineString: 从多个三维点，构造多段线.
        /// </summary>
        public static BasicCurve CreateLineStringFromPts()
        {
            //通过点集创建BasicCurve--表示的是LineString
            XPoint3d st = new XPoint3d(0, 20, 0);
            XPoint3d pt2 = new XPoint3d(10, 5, 0);
            XPoint3d pt3 = new XPoint3d(30, 30, 0);
            XPoint3d ed = new XPoint3d(40, 50, 0);

            XPoint3d[] ptList1 = { st, pt2, pt3, ed};
            BasicCurve basic = BasicCurve.CreateLineString(ptList1);
            Debug.Assert(basic.GetBasicCurveType() == BasicCurve.BasicCurveType.LineString);
            return basic;
        }

        #region 构造线段
        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建线段.
        /// 功能：构造一个水平线段.
        /// 关键类及说明：
        ///     XSegment3d: 三维线段
        /// </summary>
        public static XSegment3d CreateHorizonXseg()
        {
            //创建与seg1相交于中点的seg
            XSegment3d seg1 = CreateXSegmentFromStartEnd();
            XPoint3d st = seg1.StartPoint;
            XPoint3d ed = seg1.EndPoint;
            XPoint3d mid = (st + ed) * 0.5;

            XPoint3d left = mid - XVector3d.UnitX * 50;
            XPoint3d rigth = mid + XVector3d.UnitX * 50;
            XSegment3d seg = new XSegment3d(left, rigth);
            return seg;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建线段.
        /// 功能：构造一个线段，根据起点、终点.
        /// 关键类及说明：
        ///     XSegment3d: 三维线段
        /// </summary>
        public static XSegment3d CreateXSegmentFromStartEnd()
        {
            //通过两个点创建线段
            XPoint3d st = new XPoint3d(0, -10, 0);
            XPoint3d ed = new XPoint3d(-100, 50, 0);
            XSegment3d seg = new XSegment3d(st, ed);

            return seg;

        }
        #endregion

        #region 构造CurveSet
        /// <summary>
        /// 构造CurveSet
        /// </summary>
        public static CurveSet CreateCurveSet()
        {
            //1. 构造一个圆CurveSet.Create
            XPoint3d center = XPoint3d.Zero;
            double radius = 100;
            XVector3d normal = XVector3d.UnitZ;
            XEllipse3d arc = XEllipse3d.FromCenterRadiusNormal(center, radius, normal);
            CurveSet.BoundaryType arcBndryType = CurveSet.BoundaryType.Outer;
            CurveSet arcCurve = CurveSet.Create(arcBndryType);
            arcCurve.Add(BasicCurve.CreateArc(arc));

            //2. 构造一条直线CurveSet.Create
            XPoint3d p0 = XPoint3d.Zero;
            XPoint3d p1 = new XPoint3d(150, 0, 0);
            p0.X = -150;
            p0.Y = 20;
            p1.Y = 20;
            XSegment3d line = new XSegment3d(p0, p1);
            CurveSet.BoundaryType BndryType = CurveSet.BoundaryType.Open;
            CurveSet curveSetLine = CurveSet.Create(BndryType);
            curveSetLine.Add(BasicCurve.CreateLine(line));

            //3. 将圆和直线求交CurveCurve.IntersectionsXY
            CurveSet intersectA = new CurveSet(BndryType);
            CurveSet intersectB = new CurveSet(BndryType);
            CurveCurve.IntersectionsXY(intersectA, intersectB, arcCurve, curveSetLine);

            //4. 获取交点GetStartEnd
            XPoint3d ptStA, ptedA;
            intersectA.GetStartEnd(out ptStA, out ptedA);

            //5. 判断交点的左右
            XPoint3d ptLeft = ptStA.X < ptedA.X ? ptStA : ptedA;
            XPoint3d ptRight = ptStA.X > ptedA.X ? ptStA : ptedA;

            //6. 绘制圆弧，并转为逆时针XEllipse3dExtension.FromArcCenterStartEnd，ReverseInPlace
            XEllipse3d arcNew = SSDPNET.Geom.XEllipse3dExtension.FromArcCenterStartEnd(center, ptLeft, ptRight);
            arcNew.ReverseInPlace();

            //7.构造一条竖直的线
            double height = 500;
            XPoint3d ptBtmL = new XPoint3d();
            ptBtmL = ptLeft - XVector3d.UnitY * height;
            XSegment3d lineLeft = new XSegment3d(ptLeft, ptBtmL);
            BasicCurve basicCur = BasicCurve.CreateLine(lineLeft);

            //8.通过TransformInPlace构造CurveSet
            CurveSet curveSetRight = CurveSet.Create(BndryType);
            curveSetRight.Add(BasicCurve.CreateLine(lineLeft));

            XPoint3d centerPtL = ptLeft;
            double length = ptRight.X - ptLeft.X;
            centerPtL.X = ptLeft.X + length * 0.5;
            centerPtL.Y = ptLeft.Y - height * 0.5;
            XTransform3d trans = XTransform3d.FromRotationAroundLine(centerPtL, XVector3d.UnitZ, XAngle.PI);
            curveSetRight.TransformInPlace(trans);

            //9. 将右侧线改为逆时针 获取底边线的起终点
            curveSetRight.SetBoundaryType(CurveSet.BoundaryType.Open);
            XPoint3d ptBtmR;
            curveSetRight.GetStartPoint(out ptBtmR);
            XPoint3d[] vctPoints = { ptBtmL, ptBtmR };

            //构造一个逆时针的轮廓
            CurveSet curveSetNew = CurveSet.Create(CurveSet.BoundaryType.Outer);
            curveSetNew.Add(BasicCurve.CreateArc(arcNew));
            curveSetNew.Add(basicCur);
            //curveSetNew.Add(BasicCurve.CreateBsplineCurve(slpineCurve));
            curveSetNew.Add(BasicCurve.CreateLine(new XSegment3d(ptBtmL, ptBtmR)));
            curveSetNew.Add(curveSetRight.GetPrimitive(0));


            return curveSetNew;
        }
        #endregion

        #region 构造BsplineCurve
        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建B样条曲线.
        /// 功能：构造一个B样条曲线，指定控制点及阶数。
        /// 关键类及说明：
        ///     ATBsplineCurveExtension: B样条类 ATBsplineCurve 的扩展类，提供额外的构造方法。
        /// 关键方法：
        ///     ATBsplineCurveExtension.CreateFromPolesAndOrder: 指定控制点和阶数，拟合B样条曲线
        /// </summary>
        public static ATBsplineCurve CreateATBsplineCurves_FromControlPts(bool isPrintPts)
        {
            //用直接提供的极点、系数和节点生成B样条曲线
            XPoint3d pnt1 = new XPoint3d(-30, 0, -50);
            XPoint3d pnt2 = new XPoint3d(0, 0, 50);
            XPoint3d pnt3 = new XPoint3d(30, 0, -50);
            XPoint3d pnt4 = new XPoint3d(60, 0, 50);
            List<XPoint3d> vPts = new List<XPoint3d>() { pnt1, pnt2, pnt3, pnt4 };

            if (isPrintPts)
            {
                //把点添加到视口--调试信息
                for (int i = 0; i < vPts.Count; i++)
                {
                    UseSomeBasicMethods.AddToScene_Xpoint(vPts[i], i + 1);
                }
            }

            //vPts是控制点
            ATBsplineCurve bspine = ATBsplineCurveExtension.CreateFromPolesAndOrder(vPts, vPts.Count, 3, false);
            return bspine;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建B样条曲线.
        /// 功能：构造一个B样条曲线，指定通过点
        /// 关键类及说明：
        ///     ATBsplineCurveExtension: B样条类 ATBsplineCurve 的扩展类，提供额外的构造方法。
        /// 关键方法：
        ///     ATBsplineCurveExtension.CreateFromInterpolationAtBasisFunctionPeaks: 指定通过点，拟合B样条曲线.
        /// </summary>
        public static ATBsplineCurve CreateATBsplineCurves_FromThroughPts(bool isPrintPts)
        {
            //使用Lim拟合条件创建B样条曲线
            XPoint3d pnt1 = new XPoint3d(-30, 50, 0);
            XPoint3d pnt2 = new XPoint3d(0, -50, 0);
            XPoint3d pnt3 = new XPoint3d(30, 50, 0);
            XPoint3d pnt4 = new XPoint3d(60, -50, 0);
            XPoint3d pnt5 = new XPoint3d(90, 50, 0);
            List<XPoint3d> listPts = new List<XPoint3d>() { pnt1, pnt2, pnt3, pnt4, pnt5};

            if (isPrintPts)
            {
                //把点添加到视口--调试信息
                for (int i = 0; i < listPts.Count; i++)
                {
                    UseSomeBasicMethods.AddToScene_Xpoint(listPts[i], i + 1);
                }
            }

            //listPts 是通过点
            ATBsplineCurve slpineCurve = ATBsplineCurveExtension.CreateFromInterpolationAtBasisFunctionPeaks(listPts,(UInt64)listPts.Count, 0);
            return slpineCurve;
        }

        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建B样条曲线.
        /// 功能：构造一个B样条曲线，从 XEllipse3d 类型转换。
        /// 关键类及说明：
        ///     ATBsplineCurve: B样条类
        /// 关键方法：
        ///     ATBsplineCurve.CreateFromXEllipse3d: 将 XEllipse3d 转为B样条曲线。
        /// </summary>
        public static ATBsplineCurve CreateATBsplineCurves()
        {
            //通过构造圆弧构造ATBsplineCurve
            XPoint3d pt = new XPoint3d(0, 0, 0);
            XPoint3d pt1 = new XPoint3d(-85, 0, 0);
            XPoint3d pt2 = new XPoint3d(0, 85, 0);

            XEllipse3d elli0 = XEllipse3dExtension.FromPoints(pt, pt1, pt2, 0, 90);
            ATBsplineCurve spline1 = ATBsplineCurve.CreateFromXEllipse3d(ref elli0);
            return spline1;
        }


        /// <summary>
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/几何/创建/如何创建B样条曲线.
        /// 功能：构造一个B样条曲线，从给定的一系列点
        /// 关键类及说明：
        ///     ATBsplineCurve: B样条类
        /// 关键方法：
        ///     ATBsplineCurve.InitFromPoints: 从一系列点，初始化B样条曲线。
        /// </summary>
        public static ATBsplineCurve CreateATBsplineCurves4()
        {
            //根据一系列点创建B样条曲线
            XPoint3d pnt1 = XPoint3d.Zero;
            XPoint3d pnt2 = new XPoint3d(30, 0, 40);
            XPoint3d pnt3 = new XPoint3d(60, 0, 50);
            XPoint3d pnt4 = new XPoint3d(90, 0, 40);
            XPoint3d pnt5 = new XPoint3d(120, 0, 0);

            List<XPoint3d> listPts = new List<XPoint3d>() { pnt1, pnt2, pnt3, pnt4, pnt5 };

            ATBsplineCurve slpineCurve = CreateATBsplineCurves();
            slpineCurve.InitFromPoints(listPts, listPts.Count);

            return slpineCurve;
        }

        #endregion
    }
}
